<template>
	<div class='time-select popup'>
		<div class="content">
			<h3 class="center">可约时间选择</h3>

			<div class="container">
				<!-- 左侧 - 未来一周 -->
				<ul class="date">
					<li
						style="line-height: 61px;"
					>
						星期
					</li>
					<li
						style="line-height: 40px;"
						v-for="item in date"
						:key="item.sctWeekDay"
					>
						<div>{{item.label}}</div>
					</li>
				</ul>
				<!-- 头部 - 0:00 ~ 24:00 共48个时间 -->
				<div class="time">
					<!-- 时间段 -->
					<ul class="time-range">
						<li class="time-range-item">00:00 ~ 06:00</li>
						<li class="time-range-item">06:00 ~ 12:00</li>
						<li class="time-range-item">12:00 ~ 18:00</li>
						<li class="time-range-item">18:00 ~ 24:00</li>
					</ul>
					<!-- 0-24 -->
					<ul class="time-index">
						<li
							class="time-index-item"
							v-for="index in 24"
							:key="index"
						>
							{{index-1}}
						</li>
					</ul>
					<!-- 时间块 -->
					<div
						class="time-block"
						@mousedown="onMouseDown"
						@mousemove="onMouseMove"
						@mouseup="onMouseUp"
						@mouseleave="onMouseLeave"
					>
						<div
							class="time-block-list"
							v-for="(item,index1) in date"
							:key="item.sctWeekDay"
						>
							<div
								class="time-block-list-item"
								:class="{
									'active': time !== 0,
									'selected':isSelected(item.sctWeekDay, index2)
								}"
								v-for="(time,index2) in item.consultTime"
								:key="index2"
								:data-index1="index1"
								:data-index2="index2"
							/>
						</div>
						<!-- 选择框 -->
						<div
							v-if="showBlockSelect"
							:style="{
								'left': `${blockSelectData.left}px`,
								'top': `${blockSelectData.top}px`,
								'width': `${blockSelectData.width}px`,
								'height': `${blockSelectData.height}px`,
							}"
							class="time-block-select"
						/>
					</div>
				</div>
			</div>

			<!-- 底部， 图例，确认按键 -->
			<footer>
				<!-- 图例 -->
				<div class="left">
					<div class="leisure-hint">
						可约时间
					</div>
					<div class="selected-hint">
						选择的预约时间
					</div>
					<div class="way">
						<i class="el-icon-mouse" />
						按住左键拖动可批量选择时间
					</div>
				</div>
				<div class="btns">
					<el-button
						size="mini"
						@click="$emit('close')"
					>
						取消
					</el-button>
					<el-button
						size="mini"
						type="primary"
						@click="onclickSure"
					>
						确认
					</el-button>
				</div>
			</footer>
		</div>
	</div>
</template>

<script>
export default {
  props: {
    consultTime: {
      type: Array,
      required: true
    },
    alreadyAppointmentTime: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      date: [], // 日期数组
      showBlockSelect: false, // 展示时间选择框
      blockSelectData: {
        x: 0, // 整个时间块相对位置
        y: 0,
        startX: 0, // 鼠标点下时的位置
        startY: 0,
        left: 0, // 选择块相对时间块的起始位置
        top: 0,
        width: 0, // 选择块大小
        height: 0
      }
    }
  },
  computed: {
    isSelected() {
      return function(week, i) {
        const times = this.alreadyAppointmentTime[ week ]

        return times.indexOf(i) > -1
      }
    },
  },
  created() {
    this.initData()
  },
  methods: {
    /**
     * 初始化时间数组
     */
    initData() {
      const weekMap = {
        7: '日',
        1: '一',
        2: '二',
        3: '三',
        4: '四',
        5: '五',
        6: '六',
      }
      /* 生成24小时 48个开始时间 */

      this.date = this.consultTime.map(item => {
        /*
          recordWeek中sctStartTime记录的是可咨询的时间，将他按|拆分
          它的每个值将替换time数组中对应下标的值，也就是下标和值相等, 要注意值是字符串，因此'0'也会校验为true
        */
        const time = new Array(48).fill(0)

        item.sctStartTime.split('|').forEach(item => {
          time[ item ] = item
        })

        return {
          label: weekMap[ item.sctWeekDay ],
          sctWeekDay: item.sctWeekDay,
          consultTime: time
        }
      })

      console.log(this.date)
    },
    /**
     * 鼠标点下，激活选择框
     */
    onMouseDown(e) {
      /* 获取整个时间块相对于屏幕的位置， e.pageX是鼠标相对于屏幕的位置，两者相减等于鼠标相对于时间块的位置 */
      const { x, y } = document.querySelector('.time-block').getBoundingClientRect()

      this.blockSelectData.x = x // time-block DOM距离屏幕左侧的距离
      this.blockSelectData.y = y
      this.blockSelectData.left = e.pageX - x // 勾选框距离time-block左边界距离
      this.blockSelectData.top = e.pageY - y
      this.blockSelectData.startX = e.pageX - x // 起始点
      this.blockSelectData.startY = e.pageY - y
      this.showBlockSelect = true
    },
    /**
     * 鼠标移动，修改选框大小
     */
    onMouseMove(e) {
      if (this.showBlockSelect) {
        /* 鼠标相对整个时间块位置 */
        const mouseX = e.pageX - this.blockSelectData.x
        const mouseY = e.pageY - this.blockSelectData.y

        if (mouseX >= this.blockSelectData.startX) { // 鼠标向右移动，相对位置不用变，只需要变宽高
          this.blockSelectData.width = mouseX - this.blockSelectData.startX
        } else { // 鼠标向左移动，相对位置和宽高需要同时变
          this.blockSelectData.width = this.blockSelectData.startX - mouseX
          this.blockSelectData.left = mouseX
        }
        if (mouseY >= this.blockSelectData.startY) {
          this.blockSelectData.height = mouseY - this.blockSelectData.startY
        } else {
          this.blockSelectData.height = this.blockSelectData.startY - mouseY
          this.blockSelectData.top = mouseY
        }
      }
      e.preventDefault()
    },
    /**
     * 鼠标抬起，结束选择，计算选中的时间块并取反
     */
    onMouseUp() {
      /* 根据top和height，计算选中的纵向下标. 每个时间块高41 */
      const startY = this.blockSelectData.top
      const endY = this.blockSelectData.top + this.blockSelectData.height
      const startYIndex = Math.floor(startY / 41)
      const endYIndex = Math.floor(endY / 41)

      /* 根据left和width，计算选中的横向下标，每个时间块宽18 */
      const startX = this.blockSelectData.left
      const endX = this.blockSelectData.left + this.blockSelectData.width
      const startXIndex = Math.floor(startX / 18)
      const endXIndex = Math.floor(endX / 18)

      for (let y = startYIndex; y <= endYIndex; y++) {
        for (let x = startXIndex; x <= endXIndex; x++) {
          if (this.isSelected(y + 1, x)) { // 已经被选定的不可改
            continue
          }
          /* 反选 */
          const val = this.date[ y ].consultTime[ x ]

          this.date[ y ].consultTime[ x ] = val === 0 ? String(x) : 0
        }
      }
      this.showBlockSelect = false
      this.blockSelectData = {
        x: 0,
        y: 0,
        startX: 0,
        startY: 0,
        left: 0,
        top: 0,
        width: 0,
        height: 0
      }
    },
    /**
     * 鼠标离开, 重置
     */
    onMouseLeave() {
      this.showBlockSelect = false
      this.blockSelectData = {
        x: 0,
        y: 0,
        startX: 0,
        startY: 0,
        left: 0,
        top: 0,
        width: 0,
        height: 0
      }
    },
    /**
     * 点击确认，计算选中的时间返回
     */
    onclickSure() {
      const res = this.date.map(item => {
        return {
          sctWeekDay: item.sctWeekDay,
          sctStartTime: item.consultTime.filter(item => item !== 0).join('|')
        }
      })

      this.$emit('sure', res)
    }
  }
}
</script>

<style lang='scss' scoped>
.time-select {
  .content {
    h3 {
      margin-bottom: 10px;
      color: $blue;
    }

    ul,
    li {
      box-sizing: border-box;
    }

    .container {
      display: flex;
      width: 900px;
      font-size: $sSmall;
      color: #999999;
      user-select: none;

      .date {
        width: 35px;
        padding: 0;
        text-align: center;
        background-color: #f5f5f5;
        border: 1px solid #e6e6e6;
        border-top-left-radius: $radiusMiddle;
        border-bottom-left-radius: $radiusMiddle;

        li {
          &:not(:last-of-type) {
            border-bottom: 1px solid #e6e6e6;
          }
        }
      }

      .time {
        flex: 0 0 864px;

        .time-range {
          display: flex;
          line-height: 30px;
          background-color: #f5f5f5;
          border-top: 1px solid #e6e6e6;
          border-right: 1px solid #e6e6e6;
          border-bottom: 1px solid #e6e6e6;
          border-top-right-radius: $radiusMiddle;

          &-item {
            flex: 0 0 215px;
            text-align: center;

            &:not(:last-of-type) {
              border-right: 1px solid #e6e6e6;
            }
          }
        }

        .time-index {
          display: flex;
          line-height: 30px;
          background-color: #f5f5f5;
          border-right: 1px solid #e6e6e6;
          border-bottom: 1px solid #e6e6e6;

          &-item {
            flex: 0 0 36px;
            text-align: center;

            &:not(:last-of-type) {
              border-right: 1px solid #e6e6e6;
            }
          }
        }

        .time-block {
          &-list {
            display: flex;

            &-item {
              flex: 0 0 18px; // 不可以随便改, 与计算选框有联系
              height: 41px; // 不可以随便改
              border-right: 1px solid #e6e6e6;
              border-bottom: 1px solid #e6e6e6;

              &.active {
                background-color: $blue;
              }

              &.selected {
                background-color: $green;
              }
            }

            &:last-of-type {
              .time-detail-item:last-of-type {
                border-bottom-right-radius: $radiusMiddle;
              }
            }
          }

          /* 选择框 */
          &-select {
            position: absolute;
            background-color: rgba(75, 138, 251, 0.2);
            border: 1px solid #ff7000;
          }
        }
      }
    }

    footer {
      display: flex;
      align-items: center;
      margin-top: 10px;

      .left {
        display: flex;
        flex: 1;
        font-size: $sSmall;

        .leisure-hint,
        .selected-hint {
          display: flex;
          align-items: center;
          margin-right: 15px;

          &::before {
            width: 10px;
            height: 10px;
            margin-right: 5px;
            content: '';
          }
        }

        .leisure-hint::before {
          background-color: $blue;
        }

        .selected-hint::before {
          background-color: $green;
        }
      }
    }
  }
}
</style>
